"use strict"

var AccessToken = function(corpId, corpSecret, models, forceUpdate, cb){
  var _ = require("lodash")
    ,debug = require("debug")("wxapi")
    ,template = require("es6-template-strings")
    ,rp = require("request-promise")
    ,URLs = require('./urls.js').URLs();


  var targetUrl = template(URLs.GET_ACCESS_TOKEN, {
                    corpId: corpId,
                    corpSecret: corpSecret
                  });

  return models.CorpWechatAccessToken
    .findOne({
      where: {
        corpId: corpId
      }
    })
    .then(function(instance){
      if(forceUpdate && forceUpdate === true){
        console.error("=======>force lockforupdate")
        return models.CorpWechatAccessToken
          .lockForUpdate(corpId);
      }else{
        if(instance && !instance.isExpiring ){
          //console.error("===> got instance expiresAt: ", instance.expiresAt);
          //console.error("===> got instance isExpiring: ", instance.isExpiring);
          return;
        }else if(!instance){
          console.error("init token")
          return models.CorpWechatAccessToken.initToken(corpId);
        }else{
          //else condition just try to refresh token
          //lock for update - first of all
          console.error("=======>lockforupdate")
          return models.CorpWechatAccessToken
            .lockForUpdate(corpId);
        }
      }
    })
    .then(function(instance){
      //console.error("===>got access token instance: ", instance);
      if(!instance){
        //没有创建出缺省实例或锁定实例
        //再做一次查询，直接返回查询得到的结果
        //console.error("acces token instance got: ", instance);

        return models.CorpWechatAccessToken.findOne({
          where: {
            corpId: corpId
          }
        })
        .then(function(instance){
          if(!instance){
            return res.status(500).json({
              success: false,
              errMsg: "failed_to_retrieve_or_update_token"
            });
          }

          //console.error("get accesstoken from db: ", instance);

          return cb(null, {
            token: instance.token,
            expires_at : instance.expiresAt
          });
        })
        .catch(function(err){
          console.error("failed_to_get_token_from_db_by_corpid");
          return cb(err);
        });
      }else{
        //a locked instance created, then we need to call wechat api to get token
        var rpOptions = {
            uri: targetUrl,
            json: true // Automatically parses the JSON string in the response
        };

        rp(rpOptions)
          .then(function(data){
            console.error("wechat access_token reponse:", data)
            if(data.errcode > 0){
              console.error("failed to retrieve access token: ", data);
              throw new Error("failed_to_get_accesstoken_from_wechat_api");
            }

            //save the token and return to caller
            //{"access_token":"ACCESS_TOKEN","expires_in":7200}
            //unlock token
            return models.CorpWechatAccessToken.unlockAndUpdate(corpId, data.access_token, data.expires_in);
          })
          .then(function(instance){
            //return to caller
            return cb(null, {
              token: instance.token,
              expires_at : instance.expiresAt
            });
          })
          .catch(function(err){
            console.error(err);
            return cb(err);
          });
      }
    })
    .catch(function(err){
      console.error(err);
      return cb(err);
    });
}

module.exports = AccessToken;
